package com.smarkparking.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.wxpay.sdk.PayUtil;
import com.smarkparking.dao.OrderDao;
import com.smarkparking.pojo.Order;
import com.smarkparking.pojo.Parking;
import com.smarkparking.pojo.User;
import com.smarkparking.service.OrderService;
import com.smarkparking.service.ParkingService;
import com.smarkparking.service.UserService;
import com.smarkparking.tool.Price;
import com.smarkparking.tool.UUID;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.github.wxpay.sdk.PayConstants.ORDER_NO_KEY;
import static com.github.wxpay.sdk.PayConstants.TOTAL_FEE_KEY;

/**
 * @author 刘涛
 * @create 2021/11/19 15:38
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private UserService userService;
    @Autowired
    private ParkingService parkingService;

    @Override
    public boolean addOrder(Integer id, String email) {
        Order order = new Order();
        //获取下单的用户信息
        User user = userService.selectUserByEmail(email);
        //生成下单编号
        String orderNumber = UUID.UUIDById(email);
        order.setOrderNumber(orderNumber);
        order.setName(user.getName());
        order.setEmail(email);
        Parking parking = parkingService.selectById(id);
        order.setLicensePlateNumber(user.getLicensePlateNumber());
        if (parking.getState() == 1) {
            return false;
        }
        parkingService.updateParkingStateClose(id);
        order.setParkingSpaceNumber(parking.getParkingSpaceNumber());
        int insert = orderDao.insert(order);
        if (insert > 0) {
            return true;
        } else {
            return false;
        }

    }

    @Override
    public List<Order> findCompleteOrder(String email) {
        QueryWrapper<Order> oqw = new QueryWrapper<>();
        oqw.eq("order_state", 1);
        if (email != null) {
            oqw.eq("email", email);
        }
        List<Order> orders = orderDao.selectList(oqw);
        return orders;
    }

    @Override
    public List<Order> findNoCompleteOrder(String email) {
        QueryWrapper<Order> oqw = new QueryWrapper<>();
        oqw.eq("order_state", 0);
        if (email != null) {
            oqw.eq("email", email);
        }
        List<Order> orders = orderDao.selectList(oqw);
        return orders;
    }

    @Override
    public List<Order> findAllOrder() {
        return orderDao.selectList(null);
    }

    @Override
    public void outParking(Long id) {
        //更新时间
        Order ord = new Order();
        ord.setId(id);
        System.out.println("+++++++++++++" + new Date());
        ord.setOutTime(new Date());
        orderDao.updateById(ord);
        Order order = orderDao.selectById(id);
        //查询车位价格
        Parking parking = parkingService.selectByParkingNumber(order.getParkingSpaceNumber());
        //拿到订单金额
        Double price = Price.HPrice(order.getEntryTime(), order.getOutTime(), parking.getPrice());
        order.setOrderPrice(price);
        orderDao.updateById(order);
    }

    @Override
    public boolean pay(Long id) {
        Order order = orderDao.selectById(id);
        Parking parking = parkingService.selectByParkingNumber(order.getParkingSpaceNumber());
        parkingService.updateParkingStateOpen(parking.getId());
        order.setOrderState(1);
        int i = orderDao.updateById(order);
        if (i > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void deleteOrder(Long id) {
        orderDao.deleteById(id);
    }

    @Override
    public boolean updateOrder(Long id, String name, String parkingSpaceNumber, String licensePlateNumber, Double orderPrice, Integer orderState) {
        try {
            Order order = new Order();
            order.setId(id);
            order.setName(name);
            order.setParkingSpaceNumber(parkingSpaceNumber);
            order.setLicensePlateNumber(licensePlateNumber);
            order.setOrderPrice(orderPrice);
            order.setOrderState(orderState);
            orderDao.updateById(order);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    @Override
    public Order findOrderById(Long id) {
        Order order = orderDao.selectById(id);
        return order;
    }

    @Autowired
    private PayUtil payUtil;

    @Override
    @Transactional
    public void handleNotify(Map<String, String> data) {
        // 1.业务标示校验
        payUtil.checkResultCode(data);
        // 2.签名校验
        try {
            payUtil.checkSignature(data);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        // 3.订单状态校验（保证幂等，防止重复通知）
        String outTradeNo = data.get(ORDER_NO_KEY);
        String totalFee = data.get(TOTAL_FEE_KEY);
        log.info("开始校验回调数据，编号：{}, 金额：{}", outTradeNo, totalFee);
        if (StringUtils.isBlank(outTradeNo) || StringUtils.isBlank(totalFee)) {
            // 数据有误
            throw new RuntimeException("响应数据有误，订单金额或编号为空！");
        }
        Long orderId = Long.valueOf(outTradeNo);
        Order order = orderDao.selectById(orderId);
        log.info("开始校验订单状态，{}", order.getOrderState());
        if (Objects.equals(order.getOrderState(), 1)) {
            // 说明订单已经支付过了，属于重复通知，直接返回
            return;
        }

        // 4.订单金额校验
        log.info("开始校验订单金额，远端：{}， 本地{}", totalFee, 1);
        Long total = Long.valueOf(totalFee);
        if (!total.equals(1L)) {
            throw new RuntimeException("订单金额有误，我要报警了！");
        }
        log.info("开始修改订单状态");
        // 5.修改订单状态，更新状态和支付时间两个字段
        this.pay(orderId);
    }

    @Override
    public boolean payState(Long id) {
        Order order = orderDao.selectById(id);
        if (order.getOrderState() == 1) {
            return true;
        } else {
            return false;
        }
    }
}
